<!DOCTYPE HTML>
<html lang="en-US" manifest="../manifest.appcache">
    
    <head prefix="og: http://ogp.me/ns# book: http://ogp.me/ns/book#">
        
        
        <meta charset="UTF-8">
        <title>《The Swift Programming Language》中文版</title>

        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="robots" content="index, follow">
        <meta name="author" content="">
        <meta name="description" content="Swift 中文翻译组：364279588（要求对翻译感兴趣）">
        <meta name="keywords" content="gitbook,github" >
        <meta name="generator" content="www.gitbook.io">

        
        <link rel="next" href="../chapter2/22_Generics.html" />
        
        
        <link rel="prev" href="../chapter2/20_Extensions.html" />
        

        <meta property="og:title" content="协议 | The Swift Programming Language 中文版">
        <meta property="og:site_name" content="The Swift Programming Language 中文版">
        <meta property="og:type" content="book">
        <meta property="og:locale" content="en_US">

        <meta property="book:author" content="https://github.com/">
        <meta property="book:tag" content="GitBook">

        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black">

        <link rel="shortcut icon" href="../gitbook/images/favicon.ico" type="image/x-icon">
        
        
    </head>
    <body>
        
        

        <link rel="stylesheet" href="../gitbook/style.css">
        


        
    <div class="book"  data-level="2.21" data-basepath=".." data-revision="1402634093001">
    <div class="book-header">
    <!-- Actions Left -->
    <a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
    
    <a href="https://github.com/null" target="_blank" class="btn pull-left home-bookmark" aria-label="GitHub home"><i class="fa fa-bookmark-o"></i></a>
    
    <a href="#" class="btn pull-left toggle-search" aria-label="Toggle search"><i class="fa fa-search"></i></a>
    <span id="font-settings-wrapper">
        <a href="#" class="btn pull-left toggle-font-settings" aria-label="Toggle font settings"><i class="fa fa-font"></i>
        </a>
        <div class="dropdown-menu font-settings">
    <div class="dropdown-caret">
        <span class="caret-outer"></span>
        <span class="caret-inner"></span>
    </div>

    <div class="btn-group btn-block">
        <button id="reduce-font-size" class="btn btn-default">A</button>
        <button id="enlarge-font-size" class="btn btn-default">A</button>
    </div>

    <ul class="list-group font-family-list">
        <li class="list-group-item" data-font="0">Serif</li>
        <li class="list-group-item" data-font="1">Sans</li>
    </ul>

    <div class="btn-group btn-group-xs btn-block color-theme-list">
        <button type="button" class="btn btn-default" id="color-theme-preview-0" data-theme="0">White</button>
        <button type="button" class="btn btn-default" id="color-theme-preview-1" data-theme="1">Sepia</button>
        <button type="button" class="btn btn-default" id="color-theme-preview-2" data-theme="2">Night</button>
    </div>
</div>

    </span>

    <!-- Actions Right -->
    
    <a href="#" target="_blank" class="btn pull-right google-plus-sharing-link sharing-link" data-sharing="google-plus" aria-label="Share on Google Plus"><i class="fa fa-google-plus"></i></a>
    
    
    <a href="#" target="_blank" class="btn pull-right facebook-sharing-link sharing-link" data-sharing="facebook" aria-label="Share on Facebook"><i class="fa fa-facebook"></i></a>
    
    
    <a href="#" target="_blank" class="btn pull-right twitter-sharing-link sharing-link" data-sharing="twitter" aria-label="Share on Twitter"><i class="fa fa-twitter"></i></a>
    

    

    <!-- Title -->
    <h1>
        <i class="fa fa-spinner fa-spin"></i>
        <a href="../" >The Swift Programming Language 中文版</a>
    </h1>
</div>

    

<div class="book-summary">
    <div class="book-search">
        <input type="text" placeholder="Search" class="form-control" />
    </div>
    <ul class="summary">
        
        

        

        

        

        <li data-level="0" data-path="index.html">
            <a href="../"><i class="fa fa-check"></i> 序</a>
        </li>
        
    
        <li class="chapter " data-level="1" data-path="chapter1/chapter1.html">
            
            <a href="../chapter1/chapter1.html">
                <i class="fa fa-check"></i> <b>1.</b> 欢迎使用 Swift
            </a>
            
            
            <ul class="articles">
                
    
        <li class="chapter " data-level="1.1" data-path="chapter1/01_swift.html">
            
            <a href="../chapter1/01_swift.html">
                <i class="fa fa-check"></i> <b>1.1.</b> 关于 Swift
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="1.2" data-path="chapter1/02_a_swift_tour.html">
            
            <a href="../chapter1/02_a_swift_tour.html">
                <i class="fa fa-check"></i> <b>1.2.</b> Swift 初见
            </a>
            
            
        </li>
    

            </ul>
            
        </li>
    
        <li class="chapter " data-level="2" data-path="chapter2/chapter2.html">
            
            <a href="../chapter2/chapter2.html">
                <i class="fa fa-check"></i> <b>2.</b> Swift 教程
            </a>
            
            
            <ul class="articles">
                
    
        <li class="chapter " data-level="2.1" data-path="chapter2/01_The_Basics.html">
            
            <a href="../chapter2/01_The_Basics.html">
                <i class="fa fa-check"></i> <b>2.1.</b> 基础部分
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.2" data-path="chapter2/02_Basic_Operators.html">
            
            <a href="../chapter2/02_Basic_Operators.html">
                <i class="fa fa-check"></i> <b>2.2.</b> 基本运算符
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.3" data-path="chapter2/03_Strings_and_Characters.html">
            
            <a href="../chapter2/03_Strings_and_Characters.html">
                <i class="fa fa-check"></i> <b>2.3.</b> 字符串和字符
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.4" data-path="chapter2/04_Collection_Types.html">
            
            <a href="../chapter2/04_Collection_Types.html">
                <i class="fa fa-check"></i> <b>2.4.</b> 集合类型
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.5" data-path="chapter2/05_Control_Flow.html">
            
            <a href="../chapter2/05_Control_Flow.html">
                <i class="fa fa-check"></i> <b>2.5.</b> 控制流
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.6" data-path="chapter2/06_Functions.html">
            
            <a href="../chapter2/06_Functions.html">
                <i class="fa fa-check"></i> <b>2.6.</b> 函数
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.7" data-path="chapter2/07_Closures.html">
            
            <a href="../chapter2/07_Closures.html">
                <i class="fa fa-check"></i> <b>2.7.</b> 闭包
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.8" data-path="chapter2/08_Enumerations.html">
            
            <a href="../chapter2/08_Enumerations.html">
                <i class="fa fa-check"></i> <b>2.8.</b> 枚举
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.9" data-path="chapter2/09_Classes_and_Structures.html">
            
            <a href="../chapter2/09_Classes_and_Structures.html">
                <i class="fa fa-check"></i> <b>2.9.</b> 类和结构体
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.10" data-path="chapter2/10_Properties.html">
            
            <a href="../chapter2/10_Properties.html">
                <i class="fa fa-check"></i> <b>2.10.</b> 属性
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.11" data-path="chapter2/11_Methods.html">
            
            <a href="../chapter2/11_Methods.html">
                <i class="fa fa-check"></i> <b>2.11.</b> 方法
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.12" data-path="chapter2/12_Subscripts.html">
            
            <a href="../chapter2/12_Subscripts.html">
                <i class="fa fa-check"></i> <b>2.12.</b> 附属脚本
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.13" data-path="chapter2/13_Inheritance.html">
            
            <a href="../chapter2/13_Inheritance.html">
                <i class="fa fa-check"></i> <b>2.13.</b> 继承
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.14" data-path="chapter2/14_Initialization.html">
            
            <a href="../chapter2/14_Initialization.html">
                <i class="fa fa-check"></i> <b>2.14.</b> 构造过程
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.15" data-path="chapter2/15_Deinitialization.html">
            
            <a href="../chapter2/15_Deinitialization.html">
                <i class="fa fa-check"></i> <b>2.15.</b> 析构过程
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.16" data-path="chapter2/16_Automatic_Reference_Counting.html">
            
            <a href="../chapter2/16_Automatic_Reference_Counting.html">
                <i class="fa fa-check"></i> <b>2.16.</b> 自动引用计数
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.17" data-path="chapter2/17_Optional_Chaining.html">
            
            <a href="../chapter2/17_Optional_Chaining.html">
                <i class="fa fa-check"></i> <b>2.17.</b> 可选链
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.18" data-path="chapter2/18_Type_Casting.html">
            
            <a href="../chapter2/18_Type_Casting.html">
                <i class="fa fa-check"></i> <b>2.18.</b> 类型检查
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.19" data-path="chapter2/19_Nested_Types.html">
            
            <a href="../chapter2/19_Nested_Types.html">
                <i class="fa fa-check"></i> <b>2.19.</b> 类型嵌套
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.20" data-path="chapter2/20_Extensions.html">
            
            <a href="../chapter2/20_Extensions.html">
                <i class="fa fa-check"></i> <b>2.20.</b> 扩展
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.21" data-path="chapter2/21_Protocols.html">
            
            <a href="../chapter2/21_Protocols.html">
                <i class="fa fa-check"></i> <b>2.21.</b> 协议
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.22" data-path="chapter2/22_Generics.html">
            
            <a href="../chapter2/22_Generics.html">
                <i class="fa fa-check"></i> <b>2.22.</b> 泛型
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="2.23" data-path="chapter2/23_Advanced_Operators.html">
            
            <a href="../chapter2/23_Advanced_Operators.html">
                <i class="fa fa-check"></i> <b>2.23.</b> 高级操作符
            </a>
            
            
        </li>
    

            </ul>
            
        </li>
    
        <li class="chapter " data-level="3" data-path="chapter3/chapter3.html">
            
            <a href="../chapter3/chapter3.html">
                <i class="fa fa-check"></i> <b>3.</b> 语言参考
            </a>
            
            
            <ul class="articles">
                
    
        <li class="chapter " data-level="3.1" data-path="chapter3/01_About_the_Language_Reference.html">
            
            <a href="../chapter3/01_About_the_Language_Reference.html">
                <i class="fa fa-check"></i> <b>3.1.</b> 关于语言参考
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="3.2" data-path="chapter3/02_Lexical_Structure.html">
            
            <a href="../chapter3/02_Lexical_Structure.html">
                <i class="fa fa-check"></i> <b>3.2.</b> 词法结构
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="3.3" data-path="chapter3/03_Types.html">
            
            <a href="../chapter3/03_Types.html">
                <i class="fa fa-check"></i> <b>3.3.</b> 类型
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="3.4" data-path="chapter3/04_Expressions.html">
            
            <a href="../chapter3/04_Expressions.html">
                <i class="fa fa-check"></i> <b>3.4.</b> 表达式
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="3.5" data-path="chapter3/10_Statements.html">
            
            <a href="../chapter3/10_Statements.html">
                <i class="fa fa-check"></i> <b>3.5.</b> 语句
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="3.6" data-path="chapter3/05_Declarations.html">
            
            <a href="../chapter3/05_Declarations.html">
                <i class="fa fa-check"></i> <b>3.6.</b> 声明
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="3.7" data-path="chapter3/06_Attributes.html">
            
            <a href="../chapter3/06_Attributes.html">
                <i class="fa fa-check"></i> <b>3.7.</b> 特性
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="3.8" data-path="chapter3/07_Patterns.html">
            
            <a href="../chapter3/07_Patterns.html">
                <i class="fa fa-check"></i> <b>3.8.</b> 模式
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="3.9" data-path="chapter3/08_Generic_Parameters_and_Arguments.html">
            
            <a href="../chapter3/08_Generic_Parameters_and_Arguments.html">
                <i class="fa fa-check"></i> <b>3.9.</b> 泛型参数
            </a>
            
            
        </li>
    
        <li class="chapter " data-level="3.10" data-path="chapter3/09_Summary_of_the_Grammar.html">
            
            <a href="../chapter3/09_Summary_of_the_Grammar.html">
                <i class="fa fa-check"></i> <b>3.10.</b> 语法总结
            </a>
            
            
        </li>
    

            </ul>
            
        </li>
    


        
        <li class="divider"></li>
        <li>
            <a href="http://www.gitbook.io/" target="blank" class="gitbook-link">Generated using GitBook</a>
        </li>
<li style="margin-left:15%;"> <iframe  src="http://ghbtns.com/github-btn.html?user=numbbbbb&repo=the-swift-programming-language-in-chinese&type=watch&count=true&size=large"
  allowtransparency="true" frameborder="0" scrolling="0" width="170" height="30"></iframe></li><li><p style="padding-left:5px;padding-right:5px;">翻译无任何商业目的，仅供内部学习交流使用！</p></li><li><script src="http://s19.cnzz.com/z_stat.php?id=1000480711&web_id=1000480711" language="JavaScript"></script></li>        
    </ul>
</div>

    <div class="book-body">
        <div class="body-inner">
            <div class="page-wrapper" tabindex="-1">
                <div class="book-progress">
    <div class="bar">
        <div class="inner" style="width: 47.36842105263158%;min-width: 44.73684210526316%;"></div>
    </div>
    <div class="chapters">
    
        <a href="../index.html" title="Introduction" class="chapter done new-chapter" data-progress="0" style="left: 0%;"></a>
    
        <a href="../chapter1/chapter1.html" title="欢迎使用 Swift" class="chapter done new-chapter" data-progress="1" style="left: 2.6315789473684212%;"></a>
    
        <a href="../chapter1/01_swift.html" title="关于 Swift" class="chapter done " data-progress="1.1" style="left: 5.2631578947368425%;"></a>
    
        <a href="../chapter1/02_a_swift_tour.html" title="Swift 初见" class="chapter done " data-progress="1.2" style="left: 7.894736842105263%;"></a>
    
        <a href="../chapter2/chapter2.html" title="Swift 教程" class="chapter done new-chapter" data-progress="2" style="left: 10.526315789473685%;"></a>
    
        <a href="../chapter2/01_The_Basics.html" title="基础部分" class="chapter done " data-progress="2.1" style="left: 13.157894736842104%;"></a>
    
        <a href="../chapter2/10_Properties.html" title="属性" class="chapter done " data-progress="2.10" style="left: 15.789473684210526%;"></a>
    
        <a href="../chapter2/11_Methods.html" title="方法" class="chapter done " data-progress="2.11" style="left: 18.42105263157895%;"></a>
    
        <a href="../chapter2/12_Subscripts.html" title="附属脚本" class="chapter done " data-progress="2.12" style="left: 21.05263157894737%;"></a>
    
        <a href="../chapter2/13_Inheritance.html" title="继承" class="chapter done " data-progress="2.13" style="left: 23.68421052631579%;"></a>
    
        <a href="../chapter2/14_Initialization.html" title="构造过程" class="chapter done " data-progress="2.14" style="left: 26.31578947368421%;"></a>
    
        <a href="../chapter2/15_Deinitialization.html" title="析构过程" class="chapter done " data-progress="2.15" style="left: 28.94736842105263%;"></a>
    
        <a href="../chapter2/16_Automatic_Reference_Counting.html" title="自动引用计数" class="chapter done " data-progress="2.16" style="left: 31.57894736842105%;"></a>
    
        <a href="../chapter2/17_Optional_Chaining.html" title="可选链" class="chapter done " data-progress="2.17" style="left: 34.21052631578947%;"></a>
    
        <a href="../chapter2/18_Type_Casting.html" title="类型检查" class="chapter done " data-progress="2.18" style="left: 36.8421052631579%;"></a>
    
        <a href="../chapter2/19_Nested_Types.html" title="类型嵌套" class="chapter done " data-progress="2.19" style="left: 39.473684210526315%;"></a>
    
        <a href="../chapter2/02_Basic_Operators.html" title="基本运算符" class="chapter done " data-progress="2.2" style="left: 42.10526315789474%;"></a>
    
        <a href="../chapter2/20_Extensions.html" title="扩展" class="chapter done " data-progress="2.20" style="left: 44.73684210526316%;"></a>
    
        <a href="../chapter2/21_Protocols.html" title="协议" class="chapter done " data-progress="2.21" style="left: 47.36842105263158%;"></a>
    
        <a href="../chapter2/22_Generics.html" title="泛型" class="chapter  " data-progress="2.22" style="left: 50%;"></a>
    
        <a href="../chapter2/23_Advanced_Operators.html" title="高级操作符" class="chapter  " data-progress="2.23" style="left: 52.63157894736842%;"></a>
    
        <a href="../chapter2/03_Strings_and_Characters.html" title="字符串和字符" class="chapter  " data-progress="2.3" style="left: 55.26315789473684%;"></a>
    
        <a href="../chapter2/04_Collection_Types.html" title="集合类型" class="chapter  " data-progress="2.4" style="left: 57.89473684210526%;"></a>
    
        <a href="../chapter2/05_Control_Flow.html" title="控制流" class="chapter  " data-progress="2.5" style="left: 60.526315789473685%;"></a>
    
        <a href="../chapter2/06_Functions.html" title="函数" class="chapter  " data-progress="2.6" style="left: 63.1578947368421%;"></a>
    
        <a href="../chapter2/07_Closures.html" title="闭包" class="chapter  " data-progress="2.7" style="left: 65.78947368421052%;"></a>
    
        <a href="../chapter2/08_Enumerations.html" title="枚举" class="chapter  " data-progress="2.8" style="left: 68.42105263157895%;"></a>
    
        <a href="../chapter2/09_Classes_and_Structures.html" title="类和结构体" class="chapter  " data-progress="2.9" style="left: 71.05263157894737%;"></a>
    
        <a href="../chapter3/chapter3.html" title="语言参考" class="chapter  new-chapter" data-progress="3" style="left: 73.6842105263158%;"></a>
    
        <a href="../chapter3/01_About_the_Language_Reference.html" title="关于语言参考" class="chapter  " data-progress="3.1" style="left: 76.3157894736842%;"></a>
    
        <a href="../chapter3/09_Summary_of_the_Grammar.html" title="语法总结" class="chapter  " data-progress="3.10" style="left: 78.94736842105263%;"></a>
    
        <a href="../chapter3/02_Lexical_Structure.html" title="词法结构" class="chapter  " data-progress="3.2" style="left: 81.57894736842105%;"></a>
    
        <a href="../chapter3/03_Types.html" title="类型" class="chapter  " data-progress="3.3" style="left: 84.21052631578948%;"></a>
    
        <a href="../chapter3/04_Expressions.html" title="表达式" class="chapter  " data-progress="3.4" style="left: 86.84210526315789%;"></a>
    
        <a href="../chapter3/10_Statements.html" title="语句" class="chapter  " data-progress="3.5" style="left: 89.47368421052632%;"></a>
    
        <a href="../chapter3/05_Declarations.html" title="声明" class="chapter  " data-progress="3.6" style="left: 92.10526315789474%;"></a>
    
        <a href="../chapter3/06_Attributes.html" title="特性" class="chapter  " data-progress="3.7" style="left: 94.73684210526316%;"></a>
    
        <a href="../chapter3/07_Patterns.html" title="模式" class="chapter  " data-progress="3.8" style="left: 97.36842105263158%;"></a>
    
        <a href="../chapter3/08_Generic_Parameters_and_Arguments.html" title="泛型参数" class="chapter  " data-progress="3.9" style="left: 100%;"></a>
    
    </div>
</div>

                <div class="page-inner">
                
                    <section class="normal" id="section-gitbook_48">
                    
                        <blockquote>
<p>翻译：geek5nan</p>
<p>校对：dabing1022</p>
</blockquote>
<h1 id="-">协议</h1>
<hr>
<p>本页包含内容：</p>
<ul>
<li><a href="#protocol_syntax">协议的语法（Protocol Syntax）</a></li>
<li><a href="#property_requirements">属性要求（Property Requirements）</a></li>
<li><a href="#method_requirements">方法要求（Method Requirements）</a></li>
<li><a href="#mutating_method_requirements">突变方法要求（Mutating Method Requirements）</a></li>
<li><a href="#protocols_as_types">协议类型（Protocols as Types）</a></li>
<li><a href="#delegation">委托(代理)模式（Delegation）</a></li>
<li><a href="#adding_protocol_conformance_with_an_extension">在扩展中添加协议成员（Adding Protocol Conformance with an Extension）</a></li>
<li><a href="#declaring_protocol_adoption_with_an_extension">通过延展补充协议声明（Declaring Protocol Adoption with an Extension）</a></li>
<li><a href="#collections_of_protocol_types">集合中的协议类型（Collections of Protocol Types）</a></li>
<li><a href="#protocol_inheritance">协议的继承（Protocol Inheritance）</a></li>
<li><a href="#protocol_composition">协议合成（Protocol Composition）</a></li>
<li><a href="#checking_for_protocol_conformance">检验协议的一致性（Checking for Protocol Conformance）</a></li>
<li><a href="#optional_protocol_requirements">可选协议要求（Optional Protocol Requirements）</a></li>
</ul>
<p><code>Protocol(协议)</code>用于<strong>统一</strong>方法和属性的名称，而不实现任何功能。<code>协议</code>能够被类，枚举，结构体实现，满足协议要求的类，枚举，结构体被称为协议的<code>遵循者</code>。</p>
<p><code>遵循者</code>需要提供<code>协议</code>指定的成员，如属性，方法，操作符，下标等。</p>
<p><a name="protocol_syntax"></a></p>
<h2 id="-">协议的语法</h2>
<p><code>协议</code>的定义与类，结构体，枚举的定义非常相似，如下所示：</p>
<pre><code>protocol SomeProtocol {
    // 协议内容
}
</code></pre><p>在类，结构体，枚举的名称后加上<code>协议名称</code>，中间以冒号<code>:</code>分隔即可实现协议；实现多个协议时，各协议之间用逗号<code>,</code>分隔，如下所示：</p>
<pre><code>struct SomeStructure: FirstProtocol, AnotherProtocol {
    // 结构体内容
}
</code></pre><p>当某个类含有父类的同时并实现了协议，应当把父类放在所有的协议之前，如下所示：</p>
<pre><code>class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
    // 类的内容
}
</code></pre><p><a name="property_requirements"></a></p>
<h2 id="-">属性要求</h2>
<p><code>协议</code>能够要求其<code>遵循者</code>必须含有一些<strong>特定名称和类型</strong>的<code>实例属性(instance property)</code>或<code>类属性 (type property)</code>，也能够要求属性的<code>(设置权限)settable</code> 和<code>(访问权限)gettable</code>，但它不要求<code>属性</code>是<code>存储型属性(stored property)</code>还是<code>计算型属性(calculate property)</code>。</p>
<p>通常前置<code>var</code>关键字将属性声明为变量。在属性声明后写上<code>{ get set }</code>表示属性为可读写的。<code>{ get }</code>用来表示属性为可读的。即使你为可读的属性实现了<code>setter</code>方法，它也不会出错。</p>
<pre><code>protocol SomeProtocol {
    var musBeSettable : Int { get set }
    var doesNotNeedToBeSettable: Int { get }
}
</code></pre><p>用类来实现协议时，使用<code>class</code>关键字来表示该属性为类成员；用结构体或枚举实现协议时，则使用<code>static</code>关键字来表示：</p>
<pre><code>protocol AnotherProtocol {
    class var someTypeProperty: Int { get set }
}

protocol FullyNamed {
    var fullName: String { get }
}
</code></pre><p><code>FullyNamed</code>协议含有<code>fullName</code>属性。因此其<code>遵循者</code>必须含有一个名为<code>fullName</code>，类型为<code>String</code>的可读属性。</p>
<pre><code>struct Person: FullyNamed{
    var fullName: String
}
let john = Person(fullName: &quot;John Appleseed&quot;)
//john.fullName 为 &quot;John Appleseed&quot;
</code></pre><p><code>Person</code>结构体含有一个名为<code>fullName</code>的<code>存储型属性</code>，完整的<code>遵循</code>了协议。(<em>若协议未被完整遵循，编译时则会报错</em>)。</p>
<p>如下所示，<code>Startship</code>类<code>遵循</code>了<code>FullyNamed</code>协议：</p>
<pre><code>class Starship: FullyNamed {
    var prefix: String?
    var name: String
    init(name: String, prefix: String? = nil ) {
        self.anme = name
        self.prefix = prefix
    }
    var fullName: String {
    return (prefix ? prefix ! + &quot; &quot; : &quot; &quot;) + name
    }
}
var ncc1701 = Starship(name: &quot;Enterprise&quot;, prefix: &quot;USS&quot;)
// ncc1701.fullName == &quot;USS Enterprise&quot;
</code></pre><p><code>Starship</code>类将<code>fullName</code>实现为可读的<code>计算型属性</code>。它的每一个实例都有一个名为<code>name</code>的必备属性和一个名为<code>prefix</code>的可选属性。 当<code>prefix</code>存在时，将<code>prefix</code>插入到<code>name</code>之前来为<code>Starship</code>构建<code>fullName</code>。</p>
<p><a name="method_requirements"></a></p>
<h2 id="-">方法要求</h2>
<p><code>协议</code>能够要求其<code>遵循者</code>必备某些特定的<code>实例方法</code>和<code>类方法</code>。协议方法的声明与普通方法声明相似，但它不需要<code>方法</code>内容。</p>
<blockquote>
<p>注意：</p>
<p>协议方法支持<code>变长参数(variadic parameter)</code>，不支持<code>默认参数(default parameter)</code>。</p>
</blockquote>
<p>前置<code>class</code>关键字表示协议中的成员为<code>类成员</code>；当协议用于被<code>枚举</code>或<code>结构体</code>遵循时，则使用<code>static</code>关键字。如下所示：</p>
<pre><code>protocol SomeProtocol {
    class func someTypeMethod()
}

protocol RandomNumberGenerator {
    func random() -&gt; Double
}
</code></pre><p><code>RandomNumberGenerator</code>协议要求其<code>遵循者</code>必须拥有一个名为<code>random</code>， 返回值类型为<code>Double</code>的实例方法。(我们假设随机数在[0，1]区间内)。</p>
<p><code>LinearCongruentialGenerator</code>类<code>遵循</code>了<code>RandomNumberGenerator</code>协议，并提供了一个叫做<em>线性同余生成器(linear congruential generator)</em>的伪随机数算法。</p>
<pre><code>class LinearCongruentialGenerator: RandomNumberGenerator {
    var lastRandom = 42.0
    let m = 139968.0
    let a = 3877.0
    let c = 29573.0
    func random() -&gt; Double {
        lastRandom = ((lastRandom * a + c) % m)
        return lastRandom / m
    }
}
let generator = LinearCongruentialGenerator()
println(&quot;Here&#39;s a random number: \(generator.random())&quot;)
// 输出 : &quot;Here&#39;s a random number: 0.37464991998171&quot;
println(&quot;And another one: \(generator.random())&quot;)
// 输出 : &quot;And another one: 0.729023776863283&quot;
</code></pre><p><a name="mutating_method_requirements"></a></p>
<h2 id="-">突变方法要求</h2>
<p>能在<code>方法</code>或<code>函数</code>内部改变实例类型的方法称为<code>突变方法</code>。在<code>值类型(Value Type)</code>(<em>译者注：特指结构体和枚举</em>)中的的<code>函数</code>前缀加上<code>mutating</code>关键字来表示该函数允许改变该实例和其属性的类型。 这一变换过程在<a href="11_Methods.html#instance_methods">实例方法(Instance Methods)</a>章节中有详细描述。</p>
<p>(<em>译者注：类中的成员为<code>引用类型(Reference Type)</code>，可以方便的修改实例及其属性的值而无需改变类型；而<code>结构体</code>和<code>枚举</code>中的成员均为<code>值类型(Value Type)</code>，修改变量的值就相当于修改变量的类型，而<code>Swift</code>默认不允许修改类型，因此需要前置<code>mutating</code>关键字用来表示该<code>函数</code>中能够修改类型</em>)</p>
<blockquote>
<p>注意：</p>
<p>用<code>class</code>实现协议中的<code>mutating</code>方法时，不用写<code>mutating</code>关键字；用<code>结构体</code>，<code>枚举</code>实现协议中的<code>mutating</code>方法时，必须写<code>mutating</code>关键字。</p>
</blockquote>
<p>如下所示，<code>Togglable</code>协议含有<code>toggle</code>函数。根据函数名称推测，<code>toggle</code>可能用于<strong>切换或恢复</strong>某个属性的状态。<code>mutating</code>关键字表示它为<code>突变方法</code>：</p>
<pre><code>protocol Togglable {
    mutating func toggle()
}
</code></pre><p>当使用<code>枚举</code>或<code>结构体</code>来实现<code>Togglabl</code>协议时，必须在<code>toggle</code>方法前加上<code>mutating</code>关键字。</p>
<p>如下所示，<code>OnOffSwitch</code>枚举<code>遵循</code>了<code>Togglable</code>协议，<code>On</code>，<code>Off</code>两个成员用于表示当前状态</p>
<pre><code>enum OnOffSwitch: Togglable {
    case Off, On
    mutating func toggle() {
        switch self {
        case Off:
            self = On
        case On:
            self = Off
        }
    }
}
var lightSwitch = OnOffSwitch.Off
lightSwitch.toggle()
//lightSwitch 现在的值为 .On
</code></pre><p><a name="protocols_as_types"></a></p>
<h2 id="-">协议类型</h2>
<p><code>协议</code>本身不实现任何功能，但你可以将它当做<code>类型</code>来使用。</p>
<p>使用场景：</p>
<ul>
<li>作为函数，方法或构造器中的参数类型，返回值类型</li>
<li>作为常量，变量，属性的类型</li>
<li>作为数组，字典或其他容器中的元素类型</li>
</ul>
<blockquote>
<p>注意：</p>
<p>协议类型应与其他类型(Int，Double，String)的写法相同，使用驼峰式</p>
</blockquote>
<pre><code>class Dice {
    let sides: Int
    let generator: RandomNumberGenerator
    init(sides: Int, generator: RandomNumberGenerator) {
        self.sides = sides
        self.generator = generator
    }
    func roll() -&gt; Int {
        return Int(generator.random() * Double(sides)) +1
    }
}
</code></pre><p>这里定义了一个名为 <code>Dice</code>的类，用来代表桌游中的N个面的骰子。</p>
<p> <code>Dice</code>含有<code>sides</code>和<code>generator</code>两个属性，前者用来表示骰子有几个面，后者为骰子提供一个随机数生成器。由于后者为<code>RandomNumberGenerator</code>的协议类型。所以它能够被赋值为任意<code>遵循</code>该协议的类型。</p>
<p>此外，使用<code>构造器(init)</code>来代替之前版本中的<code>setup</code>操作。构造器中含有一个名为<code>generator</code>，类型为<code>RandomNumberGenerator</code>的形参，使得它可以接收任意遵循<code>RandomNumberGenerator</code>协议的类型。</p>
<p><code>roll</code>方法用来模拟骰子的面值。它先使用<code>generator</code>的<code>random</code>方法来创建一个[0-1]区间内的随机数种子，然后加工这个随机数种子生成骰子的面值。</p>
<p>如下所示，<code>LinearCongruentialGenerator</code>的实例作为随机数生成器传入<code>Dice</code>的<code>构造器</code></p>
<pre><code>var d6 = Dice(sides: 6,generator: LinearCongruentialGenerator())
for _ in 1...5 {
    println(&quot;Random dice roll is \(d6.roll())&quot;)
}
//输出结果
//Random dice roll is 3
//Random dice roll is 5
//Random dice roll is 4
//Random dice roll is 5
//Random dice roll is 4
</code></pre><p><a name="delegation"></a></p>
<h2 id="-">委托(代理)模式</h2>
<p>委托是一种设计模式，它允许类或结构体将一些需要它们负责的功能<code>交由(委托)</code>给其他的类型。</p>
<p>委托模式的实现很简单： 定义<code>协议</code>来<code>封装</code>那些需要被委托的<code>函数和方法</code>， 使其<code>遵循者</code>拥有这些被委托的<code>函数和方法</code>。</p>
<p>委托模式可以用来响应特定的动作或接收外部数据源提供的数据，而无需要知道外部数据源的类型。</p>
<p>下文是两个基于骰子游戏的协议：</p>
<pre><code>protocol DiceGame {
    var dice: Dice { get }
    func play()
}
protocol DiceGameDelegate {
    func gameDidStart(game: DiceGame)
    func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll:Int)
    func gameDidEnd(game: DiceGame)
}
</code></pre><p><code>DiceGame</code>协议可以在任意含有骰子的游戏中实现，<code>DiceGameDelegate</code>协议可以用来追踪<code>DiceGame</code>的游戏过程。</p>
<p>如下所示，<code>SnakesAndLadders</code>是<code>Snakes and Ladders</code>(译者注：<a href="05_Control_Flow.html">控制流</a>章节有该游戏的详细介绍)游戏的新版本。新版本使用<code>Dice</code>作为骰子，并且实现了<code>DiceGame</code>和<code>DiceGameDelegate</code>协议</p>
<pre><code>class SnakesAndLadders: DiceGame {
    let finalSquare = 25
    let dic = Dice(sides: 6, generator: LinearCongruentialGenerator())
    var square = 0
    var board: Int[]
    init() {
        board = Int[](count: finalSquare + 1, repeatedValue: 0)
        board[03] = +08; board[06] = +11; borad[09] = +09; board[10] = +02
        borad[14] = -10; board[19] = -11; borad[22] = -02; board[24] = -08
    }
     var delegate: DiceGameDelegate?
     func play() {
         square = 0
         delegate?.gameDidStart(self)
         gameLoop: while square != finalSquare {
             let diceRoll = dice.roll()
             delegate?.game(self,didStartNewTurnWithDiceRoll: diceRoll)
             switch square + diceRoll {
             case finalSquare:
                 break gameLoop
             case let newSquare where newSquare &gt; finalSquare:
                 continue gameLoop
             default:
             square += diceRoll
             square += board[square]
             }
         }
         delegate?.gameDIdEnd(self)
     }
}
</code></pre><p>游戏的<code>初始化设置(setup)</code>被<code>SnakesAndLadders</code>类的<code>构造器(initializer)</code>实现。所有的游戏逻辑被转移到了<code>play</code>方法中。</p>
<blockquote>
<p>注意：</p>
<p>因为<code>delegate</code>并不是该游戏的必备条件，<code>delegate</code>被定义为遵循<code>DiceGameDelegate</code>协议的可选属性</p>
</blockquote>
<p><code>DicegameDelegate</code>协议提供了三个方法用来追踪游戏过程。被放置于游戏的逻辑中，即<code>play()</code>方法内。分别在游戏开始时，新一轮开始时，游戏结束时被调用。</p>
<p>因为<code>delegate</code>是一个遵循<code>DiceGameDelegate</code>的可选属性，因此在<code>play()</code>方法中使用了<code>可选链</code>来调用委托方法。 若<code>delegate</code>属性为<code>nil</code>， 则委托调用<em>优雅地</em>失效。若<code>delegate</code>不为<code>nil</code>，则委托方法被调用</p>
<p>如下所示，<code>DiceGameTracker</code>遵循了<code>DiceGameDelegate</code>协议</p>
<pre><code>class DiceGameTracker: DiceGameDelegate {
    var numberOfTurns = 0
    func gameDidStart(game: DiceGame) {
        numberOfTurns = 0
        if game is SnakesAndLadders {
            println(&quot;Started a new game of Snakes and Ladders&quot;)
        }
        println(&quot;The game is using a \(game.dice.sides)-sided dice&quot;)
    }
    func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
        ++numberOfTurns
        println(&quot;Rolled a \(diceRoll)&quot;)
    }
    func gameDidEnd(game: DiceGame) {
        println(&quot;The game lasted for \(numberOfTurns) turns&quot;)
    }
}
</code></pre><p><code>DiceGameTracker</code>实现了<code>DiceGameDelegate</code>协议的方法要求，用来记录游戏已经进行的轮数。 当游戏开始时，<code>numberOfTurns</code>属性被赋值为0；在每新一轮中递加；游戏结束后，输出打印游戏的总轮数。</p>
<p><code>gameDidStart</code>方法从<code>game</code>参数获取游戏信息并输出。<code>game</code>在方法中被当做<code>DiceGame</code>类型而不是<code>SnakeAndLadders</code>类型，所以方法中只能访问<code>DiceGame</code>协议中的成员。</p>
<p><code>DiceGameTracker</code>的运行情况，如下所示：</p>
<pre><code>“let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()
// Started a new game of Snakes and Ladders
// The game is using a 6-sided dice
// Rolled a 3
// Rolled a 5
// Rolled a 4
// Rolled a 5
// The game lasted for 4 turns”
</code></pre><p><a name="adding_protocol_conformance_with_an_extension"></a></p>
<h2 id="-">在扩展中添加协议成员</h2>
<p>即便无法修改源代码，依然可以通过<code>扩展(Extension)</code>来扩充已存在类型(<em>译者注： 类，结构体，枚举等</em>)。<code>扩展</code>可以为已存在的类型添加<code>属性</code>，<code>方法</code>，<code>下标</code>，<code>协议</code>等成员。详情请在<a href="20_Extensions.html">扩展</a>章节中查看。</p>
<blockquote>
<p>注意：</p>
<p>通过<code>扩展</code>为已存在的类型<code>遵循</code>协议时，该类型的所有实例也会随之添加协议中的方法</p>
</blockquote>
<p><code>TextRepresentable</code>协议含有一个<code>asText</code>，如下所示：</p>
<pre><code>protocol TextRepresentable {
    func asText() -&gt; String
}
</code></pre><p>通过<code>扩展</code>为上一节中提到的<code>Dice</code>类遵循<code>TextRepresentable</code>协议</p>
<pre><code>extension Dice: TextRepresentable {
    cun asText() -&gt; String {
        return &quot;A \(sides)-sided dice&quot;
    }
}
</code></pre><p>从现在起，<code>Dice</code>类型的实例可被当作<code>TextRepresentable</code>类型：</p>
<pre><code>let d12 = Dice(sides: 12,generator: LinearCongruentialGenerator())
println(d12.asText())
// 输出 &quot;A 12-sided dice&quot;
</code></pre><p><code>SnakesAndLadders</code>类也可以通过<code>扩展</code>的方式来遵循协议：</p>
<pre><code>extension SnakeAndLadders: TextRepresentable {
    func asText() -&gt; String {
        return &quot;A game of Snakes and Ladders with \(finalSquare) squares&quot;
    }
}
println(game.asText())
// 输出 &quot;A game of Snakes and Ladders with 25 squares&quot;
</code></pre><p><a name="declaring_protocol_adoption_with_an_extension"></a></p>
<h2 id="-">通过延展补充协议声明</h2>
<p>当一个类型已经实现了协议中的所有要求，却没有声明时，可以通过<code>扩展</code>来补充协议声明：</p>
<pre><code>struct Hamster {
    var name: String
    func asText() -&gt; String {
        return &quot;A hamster named \(name)&quot;
    }
}
extension Hamster: TextRepresentabl {}
</code></pre><p>从现在起，<code>Hamster</code>的实例可以作为<code>TextRepresentable</code>类型使用</p>
<pre><code>let simonTheHamster = Hamster(name: &quot;Simon&quot;)
let somethingTextRepresentable: TextRepresentabl = simonTheHamester
println(somethingTextRepresentable.asText())
// 输出 &quot;A hamster named Simon&quot;
</code></pre><blockquote>
<p>注意：</p>
<p>即时满足了协议的所有要求，类型也不会自动转变，因此你必须为它做出明显的协议声明</p>
</blockquote>
<p><a name="collections_of_protocol_types"></a></p>
<h2 id="-">集合中的协议类型</h2>
<p>协议类型可以被集合使用，表示集合中的元素均为协议类型：</p>
<pre><code>let things: TextRepresentable[] = [game,d12,simoTheHamster]
</code></pre><p>如下所示，<code>things</code>数组可以被直接遍历，并调用其中元素的<code>asText()</code>函数：</p>
<pre><code>for thing in things {
    println(thing.asText())
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon
</code></pre><p><code>thing</code>被当做是<code>TextRepresentable</code>类型而不是<code>Dice</code>，<code>DiceGame</code>，<code>Hamster</code>等类型。因此能且仅能调用<code>asText</code>方法</p>
<p><a name="protocol_inheritance"></a></p>
<h2 id="-">协议的继承</h2>
<p>协议能够<em>继承</em>一到多个其他协议。语法与类的继承相似，多个协议间用逗号<code>,</code>分隔</p>
<pre><code>protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
    // 协议定义
}
</code></pre><p>如下所示，<code>PrettyTextRepresentable</code>协议继承了<code>TextRepresentable</code>协议</p>
<pre><code>protocol PrettyTextRepresentable: TextRepresentable {
    func asPrettyText() -&gt; String
}
</code></pre><p><code>遵循``PrettyTextRepresentable</code>协议的同时，也需要<code>遵循</code>TextRepresentable`协议。</p>
<p>如下所示，用<code>扩展</code>为<code>SnakesAndLadders</code>遵循<code>PrettyTextRepresentable</code>协议：</p>
<pre><code>extension SnakesAndLadders: PrettyTextRepresentable {
    func asPrettyText() -&gt; String {
        var output = asText() + &quot;:\n&quot;
        for index in 1...finalSquare {
            switch board[index] {
                case let ladder where ladder &gt; 0:
                output += &quot;▲ &quot;
            case let snake where snake &lt; 0:
                output += &quot;▼ &quot;
            default:
                output += &quot;○ &quot;
            }
        }
        return output
    }
}
</code></pre><p>在<code>for in</code>中迭代出了<code>board</code>数组中的每一个元素：</p>
<ul>
<li>当从数组中迭代出的元素的值大于0时，用<code>▲</code>表示</li>
<li>当从数组中迭代出的元素的值小于0时，用<code>▼</code>表示</li>
<li>当从数组中迭代出的元素的值等于0时，用<code>○</code>表示</li>
</ul>
<p>任意<code>SankesAndLadders</code>的实例都可以使用<code>asPrettyText()</code>方法。</p>
<pre><code>println(game.asPrettyText())
// A game of Snakes and Ladders with 25 squares:
// ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○
</code></pre><p><a name="protocol_composition"></a></p>
<h2 id="-">协议合成</h2>
<p>一个协议可由多个协议采用<code>protocol&lt;SomeProtocol, AnotherProtocol&gt;</code>这样的格式进行组合，称为<code>协议合成(protocol composition)</code>。</p>
<p>举个例子：</p>
<pre><code>protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
struct Person: Named, Aged {
    var name: String
    var age: Int
}
func wishHappyBirthday(celebrator: protocol&lt;Named, Aged&gt;) {
    println(&quot;Happy birthday \(celebrator.name) - you&#39;re \(celebrator.age)!&quot;)
}
let birthdayPerson = Person(name: &quot;Malcolm&quot;, age: 21)
wishHappyBirthday(birthdayPerson)
// 输出 &quot;Happy birthday Malcolm - you&#39;re 21!
</code></pre><p><code>Named</code>协议包含<code>String</code>类型的<code>name</code>属性；<code>Aged</code>协议包含<code>Int</code>类型的<code>age</code>属性。<code>Person</code>结构体<code>遵循</code>了这两个协议。</p>
<p><code>wishHappyBirthday</code>函数的形参<code>celebrator</code>的类型为<code>protocol&lt;Named,Aged&gt;</code>。可以传入任意<code>遵循</code>这两个协议的类型的实例</p>
<blockquote>
<p>注意：</p>
<p><code>协议合成</code>并不会生成一个新协议类型，而是将多个协议合成为一个临时的协议，超出范围后立即失效。</p>
</blockquote>
<p><a name="checking_for_protocol_conformance"></a></p>
<h2 id="-">检验协议的一致性</h2>
<p>使用<code>is</code>检验协议一致性，使用<code>as</code>将协议类型<code>向下转换(downcast)</code>为的其他协议类型。检验与转换的语法和之前相同(<em>详情查看<a href="18_Type_Casting.html">类型检查</a></em>)：</p>
<ul>
<li><code>is</code>操作符用来检查实例是否<code>遵循</code>了某个<code>协议</code>。</li>
<li><code>as?</code>返回一个可选值，当实例<code>遵循</code>协议时，返回该协议类型；否则返回<code>nil</code></li>
<li><code>as</code>用以强制向下转换型。</li>
</ul>
<pre><code>@objc protocol HasArea {
    var area: Double { get }
}
</code></pre><blockquote>
<p>注意：</p>
<p><code>@objc</code>用来表示协议是可选的，也可以用来表示暴露给<code>Objective-C</code>的代码，此外，<code>@objc</code>型协议只对<code>类</code>有效，因此只能在<code>类</code>中检查协议的一致性。详情查看<em><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216" target="_blank">Using Siwft with Cocoa and Objectivei-c</a></em>。</p>
</blockquote>
<pre><code>class Circle: HasArea {
    let pi = 3.1415927
    var radius: Double
    var area:≈radius }
    init(radius: Double) { self.radius = radius }
}
class Country: HasArea {
    var area: Double
    init(area: Double) { self.area = area }
}
</code></pre><p><code>Circle</code>和<code>Country</code>都遵循了<code>HasArea</code>协议，前者把<code>area</code>写为计算型属性（computed property），后者则把<code>area</code>写为存储型属性（stored property）。</p>
<p>如下所示，<code>Animal</code>类没有实现任何协议</p>
<pre><code>class Animal {
    var legs: Int
    init(legs: Int) { self.legs = legs }
}
</code></pre><p><code>Circle,Country,Animal</code>并没有一个相同的基类，所以采用<code>AnyObject</code>类型的数组来装载在他们的实例，如下所示：</p>
<pre><code>let objects: AnyObject[] = [
    Circle(radius: 2.0),
    Country(area: 243_610),
    Animal(legs: 4)
]
</code></pre><p>如下所示，在迭代时检查<code>object</code>数组的元素是否<code>遵循</code>了<code>HasArea</code>协议：</p>
<pre><code>for object in objects {
    if let objectWithArea = object as? HasArea {
        println(&quot;Area is \(objectWithArea.area)&quot;)
    } else {
        println(&quot;Something that doesn&#39;t have an area&quot;)
    }
}
// Area is 12.5663708
// Area is 243610.0
// Something that doesn&#39;t have an area
</code></pre><p>当数组中的元素遵循<code>HasArea</code>协议时，通过<code>as?</code>操作符将其<code>可选绑定(optional binding)</code>到<code>objectWithArea</code>常量上。</p>
<p><code>objects</code>数组中元素的类型并不会因为<code>向下转型</code>而改变，当它们被赋值给<code>objectWithArea</code>时只被视为<code>HasArea</code>类型，因此只有<code>area</code>属性能够被访问。</p>
<p><a name="optional_protocol_requirements"></a></p>
<h2 id="-">可选协议要求</h2>
<p>可选协议含有可选成员，其<code>遵循者</code>可以选择是否实现这些成员。在协议中使用<code>@optional</code>关键字作为前缀来定义可选成员。</p>
<p>可选协议在调用时使用<code>可选链</code>，详细内容在<a href="17_Optional_Chaining.html">可选链</a>章节中查看。</p>
<p>像<code>someOptionalMethod?(someArgument)</code>一样，你可以在可选方法名称后加上<code>?</code>来检查该方法是否被实现。<code>可选方法</code>和<code>可选属性</code>都会返回一个<code>可选值(optional value)</code>，当其不可访问时，<code>?</code>之后语句不会执行，并返回<code>nil</code>。</p>
<blockquote>
<p>注意：</p>
<p>可选协议只能在含有<code>@objc</code>前缀的协议中生效。且<code>@objc</code>的协议只能被<code>类</code>遵循。</p>
</blockquote>
<p><code>Counter</code>类使用<code>CounterDataSource</code>类型的外部数据源来提供<code>增量值(increment amount)</code>，如下所示：</p>
<pre><code>@objc protocol CounterDataSource {
    @optional func incrementForCount(count: Int) -&gt; Int
    @optional var fixedIncrement: Int { get }
}
</code></pre><p><code>CounterDataSource</code>含有<code>incrementForCount</code>的<code>可选方法</code>和<code>fiexdIncrement</code>的<code>可选属性</code>。</p>
<blockquote>
<p>注意：</p>
<p><code>CounterDataSource</code>中的属性和方法都是可选的，因此可以在类中声明但不实现这些成员，尽管技术上允许这样做，不过最好不要这样写。</p>
</blockquote>
<p><code>Counter</code>类含有<code>CounterDataSource?</code>类型的可选属性<code>dataSource</code>，如下所示：</p>
<pre><code>@objc class Counter {
    var count = 0
    var dataSource: CounterDataSource?
    func increment() {
        if let amount = dataSource?.incrementForCount?(count) {
            count += amount
        } else if let amount = dataSource?.fixedIncrement? {
            count += amount
        }
    }
}
</code></pre><p><code>count</code>属性用于存储当前的值，<code>increment</code>方法用来为<code>count</code>赋值。</p>
<p><code>increment</code>方法通过<code>可选链</code>，尝试从两种<code>可选成员</code>中获取<code>count</code>。</p>
<ol>
<li>由于<code>dataSource</code>可能为<code>nil</code>，因此在<code>dataSource</code>后边加上了<code>?</code>标记来表明只在<code>dataSource</code>非空时才去调用incrementForCount`方法。</li>
<li>即使<code>dataSource</code>存在，但是也无法保证其是否实现了<code>incrementForCount</code>方法，因此在<code>incrementForCount</code>方法后边也加有<code>?</code>标记。</li>
</ol>
<p>在调用<code>incrementForCount</code>方法后，<code>Int</code>型<code>可选值</code>通过<code>可选绑定(optional binding)</code>自动拆包并赋值给常量<code>amount</code>。</p>
<p>当<code>incrementForCount</code>不能被调用时，尝试使用<code>可选属性``fixedIncrement</code>来代替。</p>
<p><code>ThreeSource</code>实现了<code>CounterDataSource</code>协议，如下所示：</p>
<pre><code>class ThreeSource: CounterDataSource {
    let fixedIncrement = 3
}
</code></pre><p>使用<code>ThreeSource</code>作为数据源开实例化一个<code>Counter</code>：</p>
<pre><code>var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 {
    counter.increment()
    println(counter.count)
}
// 3
// 6
// 9
// 12
</code></pre><p><code>TowardsZeroSource</code>实现了<code>CounterDataSource</code>协议中的<code>incrementForCount</code>方法，如下所示：</p>
<pre><code>class TowardsZeroSource: CounterDataSource {
func incrementForCount(count: Int) -&gt; Int {
        if count == 0 {
            return 0
        } else if count &lt; 0 {
            return 1
        } else {
            return -1
        }
    }
}
</code></pre><p>下边是执行的代码：</p>
<pre><code>counter.count = -4
counter.dataSource = TowardsZeroSource()
for _ in 1...5 {
    counter.increment()
    println(counter.count)
}
// -3
// -2
// -1
// 0
// 0
</code></pre>
                    
                    </section>
                
                </div>
            </div>
        </div>

        
        <a href="../chapter2/20_Extensions.html" class="navigation navigation-prev " aria-label="Previous page: 扩展"><i class="fa fa-angle-left"></i></a>
        
        
        <a href="../chapter2/22_Generics.html" class="navigation navigation-next " aria-label="Next page: 泛型"><i class="fa fa-angle-right"></i></a>
        
    </div>
</div>

        

        <script src="http://cdn.bootcss.com/ace/1.1.3/ace.js"></script>
        <script src="http://cdn.bootcss.com/ace/1.1.3/mode-javascript.js"></script>
        <script src="../gitbook/jsrepl/jsrepl.js" id="jsrepl-script"></script>
        <script src="../gitbook/app.js"></script>
        

    
    <script src="../gitbook/plugins/gitbook-plugin-mixpanel/plugin.js"></script>
    

    
    <script src="http://cdn.mathjax.org/mathjax/2.0-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    

    
    <script src="../gitbook/plugins/gitbook-plugin-mathjax/plugin.js"></script>
    

<script>
require(["gitbook"], function(gitbook) {
    var config = {};
    gitbook.start(config);
});
</script>

        
    <script src="http://yandex.st/highlightjs/8.0/styles/default.min.css"></script><script src="http://yandex.st/highlightjs/8.0/highlight.min.js"></script><script text="javascript">$('pre code').each(function(i, block) {hljs.highlightBlock(block);});</script></body>
    
</html>
